﻿using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace PracticeInfluxDb
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            // You can generate a Token from the "Tokens Tab" in the UI
            const string token = "5tTAvqOqN_ZFySh2ln0wjIt6KHIoDOhiZV5o519_lherF4WXOpQcUlphRl7lSsneobfG43JoEY9GysX3MN4xcA==";
            const string bucket = "MyFirstBucket";
            const string org = "MySelf";

            var client = InfluxDBClientFactory.Create("http://localhost:8086", token.ToCharArray());

            //const string data = "mem,host=host1 used_percent=23.43234543";
            //using (var writeApi = client.GetWriteApi())
            //{
            //    writeApi.WriteRecord(bucket, org, WritePrecision.Ns, data);
            //}

            var random = new Random();

            //{
            //    var point = PointData
            //         .Measurement("mem")
            //         .Tag("host", "host1")
            //         .Field("used_percent", random.Next())
            //         .Timestamp(DateTime.UtcNow, WritePrecision.Ns);

            //    using (var writeApi = client.GetWriteApi())
            //    {
            //        writeApi.WritePoint(bucket, org, point);
            //    }

            //    var mem = new Mem { Host = "host1", UsedPercent = random.Next(), Time = DateTime.UtcNow };

            //    using (var writeApi = client.GetWriteApi())
            //    {
            //        writeApi.WriteMeasurement(bucket, org, WritePrecision.Ns, mem);
            //    }
            //}

            {
                //var point = PointData
                //     .Measurement("MyPoint")
                //     .Tag("host", "host1")
                //     .Field("value", random.Next(1, 100))
                //     .Timestamp(DateTime.UtcNow, WritePrecision.Ns);

                //using (var writeApi = client.GetWriteApi())
                //{
                //    writeApi.WritePoint(bucket, org, point);
                //}

                //var value1 = new MyPoint { Host = "host1", Value = random.Next(1, 100), Time = DateTime.UtcNow };

                //using (var writeApi = client.GetWriteApi())
                //{
                //    writeApi.WriteMeasurement(bucket, org, WritePrecision.Ns, value1);
                //}
            }

            {
                var values = new List<double>();
                var v = random.Next(1, 100);
                while (values.Any(p => p.Equals(v)))
                {
                    v = random.Next(1, 100);
                }
                var value = new MyTable { Host = "my table host", Value = v, Time = DateTime.UtcNow };
                using (var writeApi = client.GetWriteApi())
                {
                    writeApi.WriteMeasurement(bucket, org, WritePrecision.Ns, value);
                }

                values.Add(v);
            }

            var query = $"from(bucket: \"{ bucket}\") |> range(start: -1h)";
            var tables = await client.GetQueryApi().QueryAsync(query, org);

            tables.ForEach(p =>
            {
                Console.WriteLine($"{string.Join(',', p.Columns.Select(c => c.Label))}");
                Console.WriteLine($"{string.Join(',', p.Records.Select(c => c.GetValue()))}");
                Console.WriteLine($"{string.Join(',', p.Records.Select(c => c.GetField()))}");
                Console.WriteLine($"{string.Join(',', p.Records.Select(c => c.GetStart()))}");
                Console.WriteLine($"{string.Join(',', p.Records.Select(c => c.GetStop()))}");
            });
        }
    }

    // Public class
    [Measurement("mem")]
    public class Mem
    {
        [Column("host", IsTag = true)] 
        public string Host { get; set; }
        [Column("used_percent")] 
        public double? UsedPercent { get; set; }
        [Column(IsTimestamp = true)] 
        public DateTime Time { get; set; }
    }
    // Public class
    [Measurement("MyPoint")]
    public class MyPoint
    {
        [Column("host", IsTag = true)] 
        public string Host { get; set; }
        [Column("value")] 
        public double? Value { get; set; }
        [Column(IsTimestamp = true)] 
        public DateTime Time { get; set; }
    }

    [Measurement("myTable")]
    public class MyTable
    {
        [Column("host",IsTag =true)]
        public string Host { get; set; }
        [Column("value")]
        public double? Value { get; set; }
        [Column(IsTimestamp =true)]
        public DateTime Time { get; set; }
    }
}
